#include "statsxx/machine_learning/activation_functions/tanh_skewed.hpp"

// STL
#include <algorithm> // std::max()
#include <cmath>     // std::tanh(), std::atanh()


inline activation_function::tanh_skewed::tanh_skewed() {};

inline activation_function::tanh_skewed::~tanh_skewed() {};


//
//
//
inline double activation_function::tanh_skewed::f(const double x)
{
    return ( 1.7159*std::tanh(2.*x/3.) );
}

//
//
//
inline double activation_function::tanh_skewed::df(const double x)
{
    double tanhval = std::tanh(2.*x/3.);

    return ( (1.7159*2./3.)*(1. - tanhval*tanhval) );
}

//
//     F(x) = 1.7159*tanh(2.0*x/3.0)
//     define y = F(x)/1.7159
//     y = tanh(2.0*x/3.0)
//     2.0*x/3.0 = (1/2)*( log(1 + y) - log(1 - y) )
//     x = (3/4)*( log(1 + y) - log(1 - y) )
//
inline double activation_function::tanh_skewed::inv(const double fx)
{
    const double domain_extreme = 1. - 1.e-16;

    //=========================================================

    double y = fx/1.7159;

    if( y >= 1. )
    {
        y = domain_extreme;
    }
    else if( y <= -1. )
    {
        y = -domain_extreme;
    }

    return ( 1.5*std::atanh(y) );
}
